Skip to content

fix(runtime): narrow the block table, read Codex tool output, re-derive the shape counts - #229

Merged
gcko merged 4 commits into
mainfrom
fix/drc-4269-correctness-and-provenance
Aug 27, 2026
Merged

fix(runtime): narrow the block table, read Codex tool output, re-derive the shape counts#229
gcko merged 4 commits into
mainfrom
fix/drc-4269-correctness-and-provenance

Conversation

@gcko

@gcko gcko commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

The correctness and comment-accuracy half of DRC-4269. Every figure below was re-measured on the
local store rather than carried over; where my number disagrees with the finding's, I shipped mine
and say how it was measured. Two items are refuted with evidence and were not implemented.

1.1 _derive_block fires on quoted prose — FIXED

Re-measured across the whole local Claude corpus (3,774 transcripts, 2,828 with an assistant
message): the shipped table published 7 blocks. Structurally:

indicator fires trigger visible in the 200-char card context
i'm blocked 1 yes clean, sentence starts at offset 0
waiting for you (bare) 2 yes clean, short sentences
waiting for you matching your… 2 1 of 2 8 and 1 backticks before the hit on its line
not permitted 1 yes 1 backtick and 3 quotes before the hit
permission denied 1 no 472-char sentence, trigger clipped away

So 4 of 7 were the three phrases the finding names, all in a quoted or fenced span, two rendering
with no block language in the visible text.

waiting for your could not be fixed on its own: waiting for you is a prefix of it and is checked
first, so the listed waiting for your entry was dead code and giving it the first-person
treatment would have changed nothing. The fix is therefore two parts:

  • the three bare phrases are replaced by self-state forms (i'm not permitted, i am not permitted, i don't have permission, i do not have permission, i'm waiting for your, i am waiting for your), which match 0 records today;
  • an indicator must now end on a word boundary (_BLOCK_TRAILING_RE), which is what makes bare
    waiting for you stop matching the possessive, and _indicator_hit scans past a rejected hit so
    an earlier possessive cannot hide a later genuine hand-off.

Corpus effect: 7 blocks to 3, and the 3 are the clean ones above.

test_ordinary_reporting_prose_is_not_a_block gains four lines covering the three phrases plus the
prefix case. Two new tests pin the other direction:
test_the_first_person_replacements_still_report_a_real_block and
test_a_rejected_indicator_hit_does_not_hide_a_later_real_one.

1.2 The observer's stage half is unreachable on Codex — FIXED, with a measured shape

tool_result_text read record["message"], which a Codex rollout does not have. Measured before
the change: 0 of 458 local rollouts yielded a boot envelope. After: 10.

The payload shape was verified against real rollouts rather than guessed. Both spellings and both
value shapes are measured:

payload type output is a string output is a list of {type, text} blocks
function_call_output 15,730 records 897 records
custom_tool_call_output 2,956 records 18,477 records

23 rollouts name a definition_dir anywhere; 18 carry a boot envelope on one of those two payload
types; 10 have it inside the spacedock_boot_scan_bytes head window.

The provenance rule is preserved: only a tool OUTPUT counts. A function_call's arguments field
carries the same JSON on the way in and is refused, which is the same distinction Pi's toolResult
role gate makes. Three new tests cover the four shapes, the negative twin, and the untrusted-value
guards. docs/design-spacedock.md gains decision S-6 with the numbers and the rejected alternative
(event_msg/item_completed, which turns out to be CommandExecution items whose definition_dir
mention is the command line rather than its output, carrying 0 envelopes).

1.3 The Codex dedup key degrades to text — FIXED

Measured over the whole rollout store, inside the observer's own head and tail windows:
599 of 784 Codex user-message records (76.4%) carry no payload.id. (The finding said 76.6%;
mine is 76.4% and the instrument is in the report notes.)

The fallback is now positional, and that needed the windows to stop overlapping first: they overlap
completely on any file the 400 KB tail read swallows whole, so a purely positional key would have
double-counted every record. _window_lines cuts them apart on byte offsets, after which position is
a genuine identity and the id key is left doing the one job it is good at, collapsing a resumed
transcript's replayed block.

tests/_codex_message takes payload_id=None and writes the record with no id key at all.
test_a_repeated_codex_prompt_with_no_payload_id_keeps_the_newest is the regression;
test_a_replayed_record_is_still_deduped_by_its_own_id guards the other side.

One sub-claim refuted: there is no 72.6% figure anywhere in the tree (grep -rn 72.6 finds only
test digests). The _dedup_key docstring's inherited figure is "0 of 8,312 Claude and 0 of 14,389
Codex records carry a top-level id", which is a different claim and still true. The docstring now
carries the measured 76.4% with its population named.

1.4 instruction_from's unconditional title_is_prompt suppression — REFUTED, not implemented

The premise is that replacing the Python suppression with the frontend echo test would surface the
withheld characters. It would not. Measured by running instruction_from both ways over all 458
rollouts and evaluating nextInstructionEchoes (from web/next/next-boot.js) in Python:

today     {'none': 230, 'agent': 43, 'earlier': 8}
proposed  {'asked': 213, 'none': 17, 'agent': 43, 'earlier': 8}
asked lines: suppressed by the frontend 213, rendered 0, of which title was clipped 151

All 213 new lines are suppressed, including the 151 clipped-title rows that are exactly the
population the finding wanted surfaced. nextInstructionEchoes's second clause
(head.endsWith("…") && line.startsWith(head.slice(0, -1))) is written for that case and is
deliberate: line 1 clips at 80 and line 2 at 140, so one prompt reaches them as two strings.

Implementing the Python half alone would emit 213 payload fields that render nowhere and put the
same policy in two places, which is the opposite of the item's stated point. I did not implement it.
The instruction_from docstring now records the measurement so the finding is not re-derived.

web/ follow-up to file (a sibling owns that file, so it is not in this PR): relax
nextInstructionEchoes so a strictly longer extension of a clipped title is kept rather than
suppressed, then delete title_is_prompt. That is the change that surfaces the withheld characters,
and it belongs in the PR that owns web/.

3.1 The window test is vacuous and the route test is Pi-shaped — FIXED

  • test_the_head_window_and_the_tail_window_are_both_read now asserts the block as well as the
    goal. The goal lives only in the head and the block only in the tail, so it fails when either
    window is not read. test_the_tail_assertion_is_load_bearing commits the falsification: with
    read_tail stubbed to [] the goal survives and the block disappears, so if a later edit makes
    the block reachable from the head, that test goes red rather than the first one going quiet.
  • The /api/observe route test wrote a Pi-shaped type: "message" record into the Claude store,
    a shape that occurs 0 times in 3,774 real Claude transcripts. It now writes Claude-shaped records
    and asserts the block too.
  • test_the_route_answers_for_a_codex_rollout is new: a realistic rollout with session_meta,
    id-less response_item messages, the resolver matching on session_meta rather than a filename
    stem, and the sidecar written.

Non-vacuity was proved by breaking the code and watching the intended test go red, one edit at a
time (7 for 7). The exact edits are in the report notes.

3.3 No committed derivation script — FIXED

scripts/derive_prompt_shapes.py re-derives every count in the harness-injected-prompt comment
block from a store the caller points it at. Every figure now in records.py is one of its outputs.

It prints counts and shape names only, never prompt text. That constraint is in the module
docstring and enforced by _safe_label, a whitelist rather than a filter: a label must be a short
markup tag name, a literal already present in records.py's own vocabularies, or one of a fixed set
of column headings, and anything else raises UnsafeLabelError. A tag name longer than the bound is
aggregated under a structural label rather than printed, and rather than raised on, so a weird
transcript cannot make the script unusable. Discovering a new prose prefix is deliberately out of
scope, because it cannot be done without printing prose.

scripts/tests/test_derive_prompt_shapes.py seeds a distinctive prompt into a fixture store and
asserts the whole stdout carries none of it, asserts the guard rejects prompt-shaped labels, and
asserts the script's _turn_signal reimplementation agrees with the real one on seven record
shapes. Wired into the pre-PR list in AGENTS.md and into both coverage blocks in
quality-gate.yml; the script itself reports 89.3% coverage.

4.1 Three wrong figures in transcripts.py — FIXED, with my own measurements

claim was measured now how
codex_instruction walk cost 93 ms worst case 2.5 ms median, 12 ms p95, 84 ms max _codex_walk timed over all 458 rollouts
item_completed/AgentMessage reach "covers 86 of those 88" 87 of 89 files on 0.149.x carry the item; the phase == "commentary" narrowing the code applies takes it to 79 per-file scan
UserMessage as the only prompt path "4 files" 0 files (26 carry the item at all) per-file scan

The finding said 83.1 ms and 78 of 88; I measure 84 ms and 79 of 89. The docstring now separates the
two AgentMessage numbers, because conflating "the shape exists" with "the code reads it" was the
defect. The UserMessage branch is kept and now says plainly that it changes no reading today.

4.8 Comment-block provenance — FIXED

The block header now names the exact record population behind each half:

  • Codex user set: the union of 1,007 event_msg/user_message texts and 1,734 response_item
    message texts with role: "user", across 458 rollouts. That union double-counts: 974 of the
    1,007
    event_msg prompts have a matching response_item. So the counts are occurrences of a
    shape, not prompts, and the comment says so. (Equality matching scores 850; the 974 uses a
    400-character head match, because extract_text caps a block-list join at 2,000 characters while
    an event_msg's message is one uncapped string.)
  • Codex developer set: 1,826 response_item message texts with role: "developer".
  • Claude: 211,669 user-role texts across 3,774 transcripts on the collector's own glob.

One sub-claim shipped differently. The finding says "six Claude entries totalling 5,367
occurrences count records _turn_signal already refuses". Running the real records._turn_signal
over every leading-tag record gives four entries and 1,917 of the 5,393 occurrences:
local-command-caveat 1,065 of 1,065, local-command-stdout 621 of 621, system-reminder 223 of
227, channel 8 of 8. task-notification, teammate-message, bash-input, bash-stdout and
local-command-stderr are refused 0 times. I shipped my numbers.

4.9 Developer-tag counts are containment counts — FIXED

Confirmed exactly. Leading versus containment on the same corpus:

tag leading contained was documented as
permissions 338 338 410
multi_agent_mode 326 359 359
skills_instructions 80 115 388
collaboration_mode 53 122 53
app-context 2 3 3
apps_instructions 0 281 377
plugins_instructions 0 244 377

The documented set was a mix of both, which is exactly how collaboration_mode looked small. The
counts are now leading counts, labelled as such. The two that lead 0 records are kept for the
documented asymmetry (an unlisted tag renders markup as a person's words; a listed one that never
arrives costs nothing) but are labelled 0 leading (N contained) — defensive only rather than left
looking measured. turn_aborted leads 52 developer-role records and is noted on its user-set entry.

4.10 The [Image arithmetic — FIXED

Three populations, not one plus an anecdote:

shape records strip to empty carry operator text
[Image: source: …] 387 387 0
[Image source: …] 9 9 0
[Image #N] 135 1 134

The old comment said "385 of 386" and called [Image source: "the 386th". It is a separate
population of 9, and the reason the separator is a character class is [Image #N], where a space
follows Image. (The finding said 386, 9, 134/133; my corpus is one record larger on two of the
three.) The Codex <image> figure reproduces exactly at 36, all carrying operator text.

4.11 Warmup — 97 over a stated denominator, and subagent-only

I measure 97, not 85, over the Claude population the block header names. The comment now states
that denominator instead of leaving it implied, and adds the facts that matter: all 97 are
isSidechain records, 0 arrive on a Codex rollout, and _turn_signal already refuses 12 of the 97.
That is likely where the finding's 85 comes from, but I did not want to ship a number I could not
reproduce, so the comment carries mine with its population named.

4.12 Pointer comments for two duplications — FIXED

  • _turn_signal's hardcoded ("<local-command-stdout>", "<local-command-caveat>") now carries a
    note that both names are also in _CLAUDE_USER_TAGS, that this is a record rule and that is a
    text rule, that the tag set covers seven further names this must not refuse, and that a name added
    here belongs in both.
  • observer._is_generic_opener and records.injected_prompt point at each other, with the reason
    they are separate (a goal rule versus a record rule) written once in the observer.

Nits

Fixed:

  • Leading U+FEFF / U+200B / U+2060 (the one with a security shape). str.strip() removes
    whitespace and none of these is whitespace to Python, so one character in front of a record
    defeated the leading-tag regex, the prose prefixes and the whole-body set at once, and
    injected_prompt answered "the operator said this" about harness machinery. strip_prompt_wrappers
    now trims _UNSAFE_CHARS minus C0/DEL, plus U+2060 and U+FEFF; U+200C and U+200D stay out because
    they are orthographic. Test covers six lead shapes across three branches plus the other direction.
  • Double truncation deleting the ellipsis. _derive_goal_deterministic scrubbed at the cap, not
    cap + 1, so a hard-cut goal lost its . Measured: 8 of the 1,295 goals the local Claude
    corpus publishes, of which 269 clip at all. (The nit said 11 of 1,469.) Same + 1 and same reason
    as records.instruction_line.
  • shorten_paths running undocumented. One clause added where the goal is rendered. No number,
    because I did not measure the 69 and would not vouch for it.
  • _SHARED_MESSAGE_HARNESS. The comment now says the dict miss is the mechanism rather than an
    accident, and that the Droid half of the name is aspirational because resolve_transcript answers
    for claude, codex and pi only.

Skipped, with the reason:

  • Case asymmetry between the tag and prose branches. Making the prose branch case-insensitive
    would newly reject an operator writing "warmup the cache", which is the false positive
    _INJECTED_PROMPTS is matched-whole to avoid. 0 corpus incidence either way.
  • The early return that skips the prose check after an unlisted leading tag. Provably inert: a
    body that matches _PROMPT_LEADING_TAG_RE starts with <, and no listed prose prefix or
    whole-body literal starts with <. The branch cannot change an answer.
  • [Image processing] peeled as a marker. Narrowing the wrapper regex to the three measured
    spellings risks dropping an unmeasured marker variant, and the failure mode of that (publishing a
    marker as a goal) is the one this code exists to prevent. 0 corpus incidence.
  • The quadratic strip loop. As the finding says: no caller, extract_text caps at 2,000
    characters, 42 ms at 8,000 stacked markers. Not worth the complexity.
  • The unpinned <command-args> branch. I could not identify a specific defect from the
    description without guessing which regex and which branch were meant, and there is already a
    fixture exercising an empty <command-args>. Not acted on rather than acted on speculatively.
  • NO_GOAL_REASON naming a never-occurring condition. A provenance note only, and I would have
    had to run another corpus pass to vouch for a number. The docstring already explains the sentinel
    bounds the model.
  • No version signal in /api/health or write_state. Scope creep, as the finding allows.

Verification

Full pre-PR suite run once on this tree. ruff check, ruff format --check, mypy --strict,
lint_embedded.py --allow-missing-node, validate_plugins.py, bump_version.py --current all
clean. Dashboard suite 1,919 tests OK (1 skipped, pre-existing). Scripts modules 190 tests OK.
Coverage total 90.7%, fail_under 73. No manifest file is touched, so version-guard has nothing
to see.

gcko added 2 commits August 27, 2026 20:51
…ve the shape counts

DRC-4269, the correctness and comment-accuracy half.

- `_derive_block` no longer fires on quoted prose. `not permitted`,
  `permission denied` and `waiting for your` supplied 4 of the 7 blocks the
  local Claude corpus publishes and every one sat in a quoted or fenced span;
  two hit the 200-character cap with the trigger truncated away. They are
  replaced by first-person forms, and an indicator now has to end on a word
  boundary so `waiting for you` stops matching the possessive.
- `spacedock.tool_result_text` learns Codex's spelling. It read only Claude's
  and Pi's, so the observer's stage half was structurally unreachable there:
  0 of 458 local rollouts yielded a boot envelope, and 10 do now.
- The observer's head and tail windows are cut apart on byte offsets, which
  makes the dedup fallback positional. `payload.id` is absent on 76.4% of the
  Codex user records inside those windows, so the key fell through to the
  message text and a repeated prompt kept its oldest position.
- A clipped goal keeps its ellipsis: the scrub ran at the cap, not cap + 1.
- A leading U+FEFF / U+200B / U+2060 no longer defeats all three
  `injected_prompt` branches at once. That was the one degenerate class that
  failed open.
- Every count in the prompt-shape comment block is re-derived by
  `scripts/derive_prompt_shapes.py`, committed here. It prints counts and shape
  names only, never prompt text, and its guard and test say so.
- Three wrong figures in `transcripts.py` corrected against fresh measurement,
  and the developer-tag counts relabelled as the leading counts they now are.

Signed-off-by: Jared Scott <jared.scott@variable.team>
…split

sync-docs pass for the correctness branch. S-6 in design-spacedock.md carries the measured Codex payload shapes and why a function_call's arguments are not tool output; the observer and spacedock rows in the architecture map pick up the window split and the narrowed block table; CONTRIBUTING.md documents the new derivation script and its no-prompt-text guard.

Signed-off-by: Jared Scott <jared.scott@variable.team>
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Coverage

Name                                                                  Stmts   Miss Branch BrPart  Cover
-------------------------------------------------------------------------------------------------------
cargento/skills/cargento/agy_hook.py                                     79     14     28      7  78.5%
cargento/skills/cargento/cargento_runtime/__init__.py                     0      0      0      0 100.0%
cargento/skills/cargento/cargento_runtime/aggregate.py                  212      1     64      0  99.6%
cargento/skills/cargento/cargento_runtime/asks.py                       110      0     28      0 100.0%
cargento/skills/cargento/cargento_runtime/claude_data.py                305     33    142     16  89.0%
cargento/skills/cargento/cargento_runtime/cli.py                        126     14     26      3  87.5%
cargento/skills/cargento/cargento_runtime/collectors/__init__.py          0      0      0      0 100.0%
cargento/skills/cargento/cargento_runtime/collectors/antigravity.py     410     41    166     25  87.2%
cargento/skills/cargento/cargento_runtime/collectors/claude.py          261     19     94     12  90.7%
cargento/skills/cargento/cargento_runtime/collectors/codex.py            98      7     38      7  89.7%
cargento/skills/cargento/cargento_runtime/collectors/copilot.py         148      6     50      2  96.0%
cargento/skills/cargento/cargento_runtime/collectors/cursor.py          277     20    106     17  89.8%
cargento/skills/cargento/cargento_runtime/collectors/droid.py            32      3      6      1  89.5%
cargento/skills/cargento/cargento_runtime/collectors/gemini.py           53      7     16      4  84.1%
cargento/skills/cargento/cargento_runtime/collectors/goose.py            89     11     28      4  87.2%
cargento/skills/cargento/cargento_runtime/collectors/opencode.py         78      6     26      2  92.3%
cargento/skills/cargento/cargento_runtime/collectors/pi.py              326     34    152     20  88.7%
cargento/skills/cargento/cargento_runtime/config.py                     187      1     20      1  99.0%
cargento/skills/cargento/cargento_runtime/diagnostics.py                 84      4     26      4  92.7%
cargento/skills/cargento/cargento_runtime/dismissals.py                 113      2     28      2  97.2%
cargento/skills/cargento/cargento_runtime/events.py                     162      0     62      0 100.0%
cargento/skills/cargento/cargento_runtime/http_api.py                   515     31    176      9  94.2%
cargento/skills/cargento/cargento_runtime/io.py                         126      2     28      0  98.7%
cargento/skills/cargento/cargento_runtime/lifecycle.py                  323     15    104      6  95.1%
cargento/skills/cargento/cargento_runtime/notifications.py              174     14     60      4  91.5%
cargento/skills/cargento/cargento_runtime/observation.py                235      2     64      0  99.3%
cargento/skills/cargento/cargento_runtime/observer.py                   249     34    110     13  84.7%
cargento/skills/cargento/cargento_runtime/probe.py                       44      0     18      1  98.4%
cargento/skills/cargento/cargento_runtime/quota.py                      333      2    112      1  99.3%
cargento/skills/cargento/cargento_runtime/records.py                    256      5    114      9  96.2%
cargento/skills/cargento/cargento_runtime/sessions.py                   101      0     44      0 100.0%
cargento/skills/cargento/cargento_runtime/snapshot.py                    36      0      4      0 100.0%
cargento/skills/cargento/cargento_runtime/spacedock.py                  397     46    200     24  87.9%
cargento/skills/cargento/cargento_runtime/state.py                       64      0      2      0 100.0%
cargento/skills/cargento/cargento_runtime/stream.py                      57      0      8      0 100.0%
cargento/skills/cargento/cargento_runtime/transcripts.py                361     16    192     15  94.4%
cargento/skills/cargento/cargento_runtime/turns.py                      197     14    104     12  90.7%
cargento/skills/cargento/cargento_runtime/web/__init__.py                 0      0      0      0 100.0%
cargento/skills/cargento/cargento_runtime/web/page.py                    54      0     14      0 100.0%
cargento/skills/cargento/event_hook.py                                   86      4     28      3  93.9%
cargento/skills/cargento/mcp_server.py                                  377     22    112     14  92.2%
cargento/skills/cargento/notify_hook.py                                  49     15      6      1  67.3%
cargento/skills/cargento/server.py                                        3      0      2      1  80.0%
cargento/skills/cargento/statusline_hook.py                             131     13     46      8  87.0%
scripts/bench_collect.py                                                211     10     54      6  94.0%
scripts/bench_event_latency.py                                           67     67     14      0   0.0%
scripts/bump_version.py                                                  60     12     24      5  77.4%
scripts/capture_hook.py                                                 287     30     86     11  88.5%
scripts/derive_prompt_shapes.py                                         210     16     88     14  89.3%
scripts/lint_embedded.py                                                 92      3     28      2  95.8%
scripts/validate_plugins.py                                             663    186    386     58  69.3%
-------------------------------------------------------------------------------------------------------
TOTAL                                                                  8908    782   3334    344  89.7%

Threshold: fail_under in pyproject.toml · label coverage-exception to bypass (visible in PR timeline).

gcko added 2 commits August 27, 2026 21:51
…our figures

One blocking finding from an adversarial review, plus the four numbers this
branch introduced that its own review then measured as wrong. Correcting those
here rather than filing them: a PR whose subject is wrong figures in comments
should not ship four new ones, and the blocking fix already forced the round.

B2, the blocker. `_TAG_NAME_RE` admitted 40 characters while the comment three
lines above justifying the bound said "the longest name in any of `records.py`'s
vocabularies is 21 characters" -- which is right, `subagent_notification`. So a
prompt opening with `<` plus a 40-character `[A-Za-z0-9_-]` run terminated by
whitespace reached stdout verbatim through the unlisted-tag branch, falsifying
this module's own docstring and CONTRIBUTING.md on the one script whose job is
to read every prompt in the store. The existing negative case was 44 characters,
one class above the bound, so it proved rejection at 44 and never probed 40.

Lowered to 24. The longer vocabulary entries are prose prefixes that reach
stdout through `_safe_label`'s membership clauses, not through this pattern, so
narrowing it cannot reject them. The discovery affordance survives: over 3,774
local Claude transcripts there are exactly 2 distinct unlisted leading tag names
occurring more than once, both 21 characters or shorter, and 0 occurrences of
the over-long aggregate. Boundary now pinned at 21, 24 and 25, plus a case
proving an over-long name aggregates rather than printing itself.

B1. Decision S-6 said 18 rollouts carry a boot envelope and the docstring said
12 arrive on a `function_call_output`. Measured with the shipped
`boot_records` over the collector's own glob: 14 files carry an envelope the
reader PARSES (9 `function_call_output`, 6 `custom_tool_call_output`, one file
both), 50 records, 43 of them on `function_call_output`. 18 and 12 count files
whose record holds a `{"command"` CANDIDATE object, parsed or not -- a different
question, now recorded as such so nobody re-derives it and reads it as a
regression.

B3. The "599 of 784" id-absence figure was measured on the `head + read_tail`
concatenation this same commit replaces with disjoint windows, so it was a count
taken on the double-counting instrument whose double-counting the commit fixes.
The disjoint windows give 500 of 655. Both are 76.3%, which is the point worth
making, so the docstring now gives both and names the instrument.

B4. `channel` is the fourth `_turn_signal`-refused entry and was the only one
unmarked, while the header's total needs it: 1,065 + 621 + 223 + 8 = 1,917.

B5. The branch deleted the denominator that made "~95%" correct. Over the
population the sentence then named it was 82.9%. Restored as 294 of 305 release
builds (96.4%), with the prerelease split stated: folding the 0.145.0-alpha
files back in gives 296 of 357, because `phase == "commentary"` reached 1 of 51
alpha files. A prerelease is the one population where the shape was mid-move.

Refs DRC-4269

Signed-off-by: Jared Scott <jared.scott@variable.team>
One conflict, in `tests/test_observer.py`, and it was the shape AGENTS.md warns
about: both sides added a test at the same insertion point, so each side's hunk
was correct for a tree that no longer exists. Resolved as a union rather than a
choice, because all three tests are wanted:

- `test_the_first_person_replacements_still_report_a_real_block` (this branch,
  the 1.1 narrowing)
- `test_a_rejected_indicator_hit_does_not_hide_a_later_real_one` (this branch)
- `test_a_block_past_the_publish_cap_is_still_found` (from #230, the
  `extract_text` cap regression)

The import line conflicted for the same reason and needs all three names:
`runtime_io` from this branch, `records` from #230.

Verified on the merged tree rather than on the resolution: 1,934 dashboard tests
OK and 192 scripts tests OK, ruff, ruff format, mypy --strict and
validate_plugins all clean.

Signed-off-by: Jared Scott <jared.scott@variable.team>
@gcko
gcko merged commit 0f9d086 into main Aug 27, 2026
13 checks passed
@gcko
gcko deleted the fix/drc-4269-correctness-and-provenance branch August 27, 2026 14:08
gcko added a commit that referenced this pull request Aug 27, 2026
AGENTS.md's Parallel Work section says to leave this marker alone per branch and
stamp it once from main after the merges, naming what the range actually covers.
Three parallel branches just landed, so this is that stamp.

11730b5..0f9d086 is eleven commits: the v0.16.0 release, the five PRs that built
the instruction line and the redaction filter (#220, #222, #223, #225, #226),
the review-calibration and CI-detector change (#227), and the three DRC-4269
follow-ups that cleared the deferred-findings backlog (#228, #229, #230).

Each of those PRs carried its own doc updates, and the three DRC-4269 branches
deliberately did not touch this line so they could not collide on it. What this
stamp vouches for is that range as a whole: the design docs, SECURITY.md and the
runtime architecture module map were reconciled against the code inside the PRs
that changed it, and several figures in them were re-derived rather than carried
forward.

Signed-off-by: Jared Scott <jared.scott@variable.team>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant